﻿namespace com.crownpack
{
    using System;
    using System.Collections.Generic;

    using com.crownpack.Extensions.DoubleExtensions;
    using com.crownpack.Extensions.StringExtensions;
    using com.crownpack.Extensions.SymbolExtensions;
    using com.crownpack.InitiativesDao;

    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;

    using ReferenceObject = InitiativesDao.InitiativesConfiguration;

    /// <summary>
    /// List Item Events
    /// </summary>
    public class InitiativesConfigurationItemEventReceiver : SPItemEventReceiver
    {
        #region Fields

        string _sourceListInternalName;

        #endregion Fields

        #region Properties

        string entityName
        {
            get;
            set;
        }

        string sourceListInternalName
        {
            get
            {
                if ( string.IsNullOrEmpty( _sourceListInternalName ) )
                {
                    ReferenceObject o = null;
                    _sourceListInternalName = Item.GetColumnName<ReferenceObject>( o.GetPropertySymbol( a => a.SourceList ) );
                }
                return _sourceListInternalName;
            }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// An item is being added.
        /// </summary>
        public override void ItemAdding( SPItemEventProperties properties )
        {
            if ( isActive( properties ) )
            {
                string redirectUrl = string.Empty;
                bool ok = validateConnection( properties, ref redirectUrl );
                if ( ok )
                {
                    properties.AfterProperties[ sourceListInternalName ] = entityName;
                }
                else
                {
                    properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                    properties.RedirectUrl = redirectUrl.Replace( "//", "/" );
                }
            }
        }

        /// <summary>
        /// An item is being updated.
        /// </summary>
        public override void ItemUpdating( SPItemEventProperties properties )
        {
            if ( isActive( properties ) )
                if ( !hasClientSiteUrlChanged( properties ) )
                {
                    string redirectUrl = string.Empty;
                    bool ok = validateConnection( properties, ref redirectUrl );
                    if ( ok )
                    {
                        properties.AfterProperties[ sourceListInternalName ] = entityName;
                    }
                    else
                    {
                        properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                        properties.RedirectUrl = redirectUrl.Replace( "//", "/" );
                    }
                }
        }

        int? getParentCustomerNo( SPItemEventProperties properties )
        {
            ReferenceObject o = null;
            string internalName = Item.GetColumnName<ReferenceObject>( o.GetPropertySymbol( a => a.ParentCustomerNo ) );

            double? d = properties.AfterProperties[ internalName ].ToString( ).ToNullableDouble( );
            return d.HasValue ? d.Value.ToInt32( ) : new int?( );
        }

        string getSourceList( SPItemEventProperties properties )
        {
            return properties.AfterProperties[ sourceListInternalName ].ToString( );
        }

        bool hasClientSiteUrlChanged( SPItemEventProperties properties )
        {
            ReferenceObject o = null;
            string internalName = Item.GetColumnName<ReferenceObject>( o.GetPropertySymbol( a => a.ClientSite ) );

            if ( !properties.ListItem[ internalName ].Equals( properties.AfterProperties[ internalName ] ) )
            {
                string title = properties.ListItem.Fields.GetFieldByInternalName( internalName ).Title;
                properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                properties.RedirectUrl = string.Concat( properties.RelativeWebUrl, MessageHandler.GetRedirectUrl( MessageHandler.Message.ClientSiteUrl.ClientSiteUrlCannotBeChanged, title ) );

                return true;
            }
            else
                return false;
        }

        bool isActive( SPItemEventProperties properties )
        {
            ReferenceObject o = null;
            string internalName = Item.GetColumnName<ReferenceObject>( o.GetPropertySymbol( a => a.Active ) );

            return properties.AfterProperties[ internalName ].ToString( ).ToBoolean( );
        }

        bool validateConnection( SPItemEventProperties properties, ref string redirectUrl )
        {
            bool ok = false;
            string _redirectUrl = string.Empty;
            int? parentCustomerNo = getParentCustomerNo( properties );
            if ( parentCustomerNo.HasValue )
            {
                string sourceList = getSourceList( properties );
                if ( !string.IsNullOrEmpty( sourceList ) )
                {
                    try
                    {
                        SPSecurity.RunWithElevatedPrivileges( delegate( )
                            {
                                CustomerDao dao = new CustomerDao( properties.WebUrl );
                                try
                                {
                                    entityName = dao.GetEntityName( sourceList );
                                }
                                catch ( Exception e )
                                {
                                    //properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                                    //properties.RedirectUrl =
                                    _redirectUrl = string.Concat( properties.RelativeWebUrl, MessageHandler.GetRedirectUrl( MessageHandler.Message.Connection.AccessToExternalContentTypeFailed, sourceList, e.Message, e.StackTrace, e.InnerException == null ? string.Empty : e.InnerException.Message ) );
                                    return;
                                }
                                if ( !string.IsNullOrEmpty( entityName ) )
                                {
                                    List<Customer> list = dao.GetByParentCustomerNo( parentCustomerNo.Value, entityName );
                                    if ( list.Count > 0 )
                                        ok = true;
                                    else
                                    {
                                        //properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                                        //properties.RedirectUrl =
                                        _redirectUrl = string.Concat( properties.RelativeWebUrl, MessageHandler.GetRedirectUrl( MessageHandler.Message.Connection.ParentCustomerNumberNotFound, sourceList, parentCustomerNo.Value ) );
                                    }
                                }
                                else
                                {
                                    //properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                                    //properties.RedirectUrl =
                                    _redirectUrl = string.Concat( properties.RelativeWebUrl, MessageHandler.GetRedirectUrl( MessageHandler.Message.Connection.ExternalContentTypeNotFound, sourceList, parentCustomerNo.Value ) );
                                }
                            } );
                    }
                    catch ( Exception e )
                    {
                        //properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
                        //properties.RedirectUrl =
                        _redirectUrl = string.Concat( properties.RelativeWebUrl, MessageHandler.GetRedirectUrl( MessageHandler.Message.Connection.AccessToExternalContentTypeFailed, sourceList, e.Message, e.StackTrace, e.InnerException == null ? string.Empty : e.InnerException.Message ) );
                    }
                }
            }
            redirectUrl = _redirectUrl;
            return ok;
        }

        #endregion Methods
    }
}